Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change the aarch64 elf version in template file and reassemble #19871

Merged
merged 1 commit into from
Feb 18, 2025

Conversation

bwatters-r7
Copy link
Contributor

@bwatters-r7 bwatters-r7 commented Feb 11, 2025

It turns out we are using ELF version 0 for aarch64 staged elf payloads. There's no such version. In fact, there has ever only been version 1. See https://en.wikipedia.org/wiki/Executable_and_Linkable_Format for the value in offset 0x14.

This just sets that value to 1. It does not fix all the problems we have seen, but it does allow debuggers and other tools to work so we can figure out why it is failing.

Related:
#19841
#19865

Testing

Old

msf6 payload(cmd/linux/https/x64/meterpreter_reverse_tcp) > use payload/linux/aarch64/meterpreter/reverse_tcp
msf6 payload(linux/aarch64/meterpreter/reverse_tcp) > set lhost 10.5.135.201
lhost => 10.5.135.201
msf6 payload(linux/aarch64/meterpreter/reverse_tcp) > generate -f elf -o aarch64_staged.elf
[*] Writing 332 bytes to aarch64_staged.elf...
msf6 payload(linux/aarch64/meterpreter/reverse_tcp) > file aarch64_staged.elf
[*] exec: file aarch64_staged.elf

aarch64_staged.elf: ELF 64-bit LSB executable, ARM aarch64, invalid version (SYSV), statically linked, no section header
msf6 payload(linux/aarch64/meterpreter/reverse_tcp) > readelf -a aarch64_staged.elf
[*] exec: readelf -a aarch64_staged.elf

ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           AArch64
  Version:                           0x0
  Entry point address:               0x400078
  Start of program headers:          64 (bytes into file)
  Start of section headers:          0 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         1
  Size of section headers:           0 (bytes)
  Number of section headers:         0
  Section header string table index: 0

There are no sections in this file.

There are no section groups in this file.

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  LOAD           0x0000000000000000 0x0000000000400000 0x0000000000400000
                 0x000000000000014c 0x0000000000000220  RWE    0x1000

There is no dynamic section in this file.

There are no relocations in this file.

The decoding of unwind sections for machine type AArch64 is not currently supported.

Dynamic symbol information is not available for displaying symbols.

No version information found in this file.
msf6 payload(linux/aarch64/meterpreter/reverse_tcp) > 

New

msf6 payload(cmd/linux/https/x64/meterpreter_reverse_tcp) > use payload/linux/aarch64/meterpreter/reverse_tcp 
msf6 payload(linux/aarch64/meterpreter/reverse_tcp) > set lhost 10.5.135.201
lhost => 10.5.135.201
msf6 payload(linux/aarch64/meterpreter/reverse_tcp) > generate -f elf -o aarch64_staged.elf
[*] Writing 332 bytes to aarch64_staged.elf...
msf6 payload(linux/aarch64/meterpreter/reverse_tcp) > file aarch64_staged.elf
[*] exec: file aarch64_staged.elf

aarch64_staged.elf: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), statically linked, no section header
msf6 payload(linux/aarch64/meterpreter/reverse_tcp) > readelf -a aarch64_staged.elf
[*] exec: readelf -a aarch64_staged.elf

ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           AArch64
  Version:                           0x1
  Entry point address:               0x400078
  Start of program headers:          64 (bytes into file)
  Start of section headers:          0 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         1
  Size of section headers:           0 (bytes)
  Number of section headers:         0
  Section header string table index: 0

There are no sections in this file.

There are no section groups in this file.

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  LOAD           0x0000000000000000 0x0000000000400000 0x0000000000400000
                 0x000000000000014c 0x0000000000000220  RWE    0x1000

There is no dynamic section in this file.

There are no relocations in this file.

The decoding of unwind sections for machine type AArch64 is not currently supported.

Dynamic symbol information is not available for displaying symbols.

No version information found in this file.

@smcintyre-r7 smcintyre-r7 added bug rn-fix release notes fix payload labels Feb 14, 2025
@bcoles
Copy link
Contributor

bcoles commented Feb 15, 2025

Strange that we ever did this. Every other template specifies an e_version of 1.

# grep -rn e_version data/templates/src/elf/
data/templates/src/elf/dll/elf_dll_x86_template.s:11:  dd    1                          ; e_version = EV_CURRENT
data/templates/src/elf/dll/elf_dll_riscv32le_template.s:13:  dd    1                          ; e_version = EV_CURRENT
data/templates/src/elf/dll/elf_dll_armle_template.s:11:  dd    1                          ; e_version = EV_CURRENT
data/templates/src/elf/dll/elf_dll_aarch64_template.s:11:  dd    1                        ;   e_version
data/templates/src/elf/dll/elf_dll_x64_template.s:11:  dd    1                          ; e_version = EV_CURRENT
data/templates/src/elf/dll/elf_dll_riscv64le_template.s:13:  dd    1                        ;   e_version
data/templates/src/elf/exe/elf_x86_solaris_template.s:13:  dd    1                        ;   e_version
data/templates/src/elf/exe/elf_armle_template.s:13:  dd    1                        ;   e_version
data/templates/src/elf/exe/elf_aarch64_template.s:12:  dd    0                        ;   e_version
data/templates/src/elf/exe/elf_loongarch64_template.s:14:  dd    1                        ;   e_version
data/templates/src/elf/exe/elf_mipsle_template.s:13:  dd    1                        ;   e_version
data/templates/src/elf/exe/elf_x86_bsd_template.s:13:  dd    1                        ;   e_version
data/templates/src/elf/exe/elf_riscv64le_template.s:13:  dd    1                        ;   e_version
data/templates/src/elf/exe/elf_riscv32le_template.s:13:  dd    1                        ;   e_version
data/templates/src/elf/exe/elf_x86_template.s:13:  dd    1                        ;   e_version

Copy link
Contributor

@bcoles bcoles left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Untested, but the code changes make sense.

The compiled file changes match the PR description:

# hexdump -C new-template_aarch64_linux.bin > a
# hexdump -C data/templates/template_aarch64_linux.bin > b
# diff -u a b
--- a   2025-02-15 07:43:27.172159925 -0500
+++ b   2025-02-15 07:43:31.393529202 -0500
@@ -1,5 +1,5 @@
 00000000  7f 45 4c 46 02 01 01 00  00 00 00 00 00 00 00 00  |.ELF............|
-00000010  02 00 b7 00 01 00 00 00  78 00 40 00 00 00 00 00  |........x.@.....|
+00000010  02 00 b7 00 00 00 00 00  78 00 40 00 00 00 00 00  |........x.@.....|
 00000020  40 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |@...............|
 00000030  00 00 00 00 40 00 38 00  01 00 00 00 00 00 00 00  |[email protected].........|
 00000040  01 00 00 00 07 00 00 00  00 00 00 00 00 00 00 00  |................|

The other existing aarch64 Linux template (template_aarch64_linux_dll.bin) already uses ELF version 1.

# readelf -h data/templates/template_aarch64_linux*

File: data/templates/template_aarch64_linux.bin
ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           AArch64
  Version:                           0x0
  Entry point address:               0x400078
  Start of program headers:          64 (bytes into file)
  Start of section headers:          0 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         1
  Size of section headers:           0 (bytes)
  Number of section headers:         0
  Section header string table index: 0

File: data/templates/template_aarch64_linux_dll.bin
ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              DYN (Shared object file)
  Machine:                           AArch64
  Version:                           0x1
  Entry point address:               0x1a0
  Start of program headers:          64 (bytes into file)
  Start of section headers:          176 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         2
  Size of section headers:           64 (bytes)
  Number of section headers:         2
  Section header string table index: 1
readelf: Error: no .dynamic section in the dynamic segment

@msutovsky-r7 msutovsky-r7 self-assigned this Feb 17, 2025
@msutovsky-r7 msutovsky-r7 merged commit 0d87703 into rapid7:master Feb 18, 2025
64 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug payload rn-fix release notes fix
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

4 participants